package org.niugang.config;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.context.annotation.Configuration;
import org.springframework.core.annotation.Order;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.security.oauth2.config.annotation.configurers.ClientDetailsServiceConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configuration.AuthorizationServerConfigurerAdapter;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableAuthorizationServer;
import org.springframework.security.oauth2.config.annotation.web.configuration.EnableResourceServer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerEndpointsConfigurer;
import org.springframework.security.oauth2.config.annotation.web.configurers.AuthorizationServerSecurityConfigurer;
import org.springframework.security.oauth2.provider.error.WebResponseExceptionTranslator;
import org.springframework.security.oauth2.provider.token.store.redis.RedisTokenStore;


@Configuration
/*
 * 在当前应用程序上下文中启用授权服务器(即AuthorizationEndpoint和TokenEndpoint)的便利注释，
 * 它必须是一个DispatcherServlet上下文。服务器的许多特性可以通过使用AuthorizationServerConfigurer类型的@
 * bean来定制(例如，通过扩展AuthorizationServerConfigurerAdapter)。用户负责使用正常的Spring安全特性(
 * 
 * @EnableWebSecurity等)来保护授权端点(/oauth/授权)，但是令牌端点(/oauth/ Token)将通过客户端凭证上的HTTP基本身份验证自动获得。
 * 客户端必须通过一个或多个AuthorizationServerConfigurers提供一个ClientDetailsService来注册。
 */
/**
 * 
 * @ClassName:  AuthorizationServerConfiguration   
 * @Description:认证服务器 
 * @author: niugang
 * @date:   2018年9月5日 下午8:10:29   
 * @Copyright: 863263957@qq.com. All rights reserved. 
 *
 */
//@EnableAuthorizationServer
//@EnableResourceServer // 程序需要对外暴露获取Token的api和验证Token的API,所以程序也是一个资源服务器
//@Order(6)
public class AuthorizationServerConfiguration extends AuthorizationServerConfigurerAdapter {
	// 模拟第三方调用api
	private static final String DEMO_RESOURCE_ID = "api";


	/**
	 * 这个Bean是在WebSecurityConfigurerAdapter中定义的
	 */
	@Autowired
	@Qualifier("authenticationManagerBean")
	AuthenticationManager authenticationManager;
	@Autowired
	RedisConnectionFactory redisConnectionFactory;
	@Autowired
	private UserDetailsService userDetailsService;

	@Autowired
	private WebResponseExceptionTranslator customWebResponseExceptionTranslator;


	/**accessTokenValiditySeconds:设置token无效时间,秒
	 * refreshTokenValiditySeconds：设置refresh_token无效时间秒
	 */
	// 配置客户端信息
	@Override
	public void configure(ClientDetailsServiceConfigurer clients) throws Exception {
		// 配置两个客户端,一个用于password认证一个用于client认证
		// 默认token的有效期为12小时
		//基于内存的
		clients.inMemory().withClient("client_1")// 基于客户端认证的
				.resourceIds(DEMO_RESOURCE_ID).authorizedGrantTypes("client_credentials", "refresh_token")
				.scopes("select").authorities("client").secret("123456")// .refreshTokenValiditySeconds(3600).accessTokenValiditySeconds(20)
				.and().withClient("client_2")// 基于密码的
				.resourceIds(DEMO_RESOURCE_ID).authorizedGrantTypes("password", "refresh_token").scopes("server")
				.authorities("client")//// *.refreshTokenValiditySeconds(3600).accessTokenValiditySeconds(60)*/;
				.secret("123456").and().withClient("client_3")// 基于CODE
				.resourceIds(DEMO_RESOURCE_ID)
				.authorizedGrantTypes("authorization_code", "refresh_token","password", "implicit")
				.scopes("server").authorities("client").secret("123456");
		
		//.redirectUris("http://ww.baidu.com")   指定了url就不需要二次去人  ，没有指定需要二次确认  （可能提示为 你确定授权给xxx吗）

	}

	@Override
	public void configure(AuthorizationServerEndpointsConfigurer endpoints) throws Exception {
		endpoints.// token存储策略
				tokenStore(new RedisTokenStore(redisConnectionFactory))// token存储在redis中
				// 开起密码认证
				.authenticationManager(authenticationManager).userDetailsService(userDetailsService);// 密码模式需要在数据库中进行认证

		endpoints.exceptionTranslator(customWebResponseExceptionTranslator);// 错误异常
		
	}

	@Override
	public void configure(AuthorizationServerSecurityConfigurer oauthServer) throws Exception {
		// 允许表单认证
		oauthServer.allowFormAuthenticationForClients();


	}
}
